package com.zaofan.mobile.controller;

import java.io.IOException;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.dbutils.QueryRunner;

import com.alipay.util.AlipayNotify;
import com.zaofan.bean.Account;
import com.zaofan.bean.AccountLog;
import com.zaofan.bean.Error;
import com.zaofan.bean.Goods;
import com.zaofan.bean.GoodsOrderDetail;
import com.zaofan.bean.GoodsOrderInfo;
import com.zaofan.bean.OrderDetail;
import com.zaofan.bean.OrderInfo;
import com.zaofan.bean.OrderPay;
import com.zaofan.bean.Product;
import com.zaofan.bean.Shop;
import com.zaofan.constant.StateConstant;
import com.zaofan.constant.TypeConstant;
import com.zaofan.service.AccountService;
import com.zaofan.service.ErrorService;
import com.zaofan.service.GoodsOrderDetailService;
import com.zaofan.service.GoodsOrderInfoService;
import com.zaofan.service.GoodsService;
import com.zaofan.service.OrderDetailService;
import com.zaofan.service.OrderInfoService;
import com.zaofan.service.OrderPayService;
import com.zaofan.service.ProductService;
import com.zaofan.service.ShopService;
import com.zaofan.utils.C3p0DataSourceUtils;
import com.zaofan.utils.JPushUtils;
import com.zaofan.utils.SqlBuilderUtils;

@WebServlet("/alipay_goods_notify")
public class AlipayPayGoodsController extends HttpServlet {

	private static final long serialVersionUID = 5035453965360402957L;
	private GoodsOrderInfoService orderInfoService = new GoodsOrderInfoService();
	private OrderPayService orderPayService = new OrderPayService();
	
	private AccountService accountService = new AccountService();
	private AccountLog accountLog = new AccountLog();
	private ErrorService errorService = new ErrorService();
	private GoodsOrderDetailService orderDetailService = new GoodsOrderDetailService();
	private GoodsService productService = new GoodsService();

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		System.err.println("alipay in ");

		Map<String, String> params = new HashMap<String, String>();
		Map requestParams = request.getParameterMap();
		for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
			String name = (String) iter.next();
			String[] values = (String[]) requestParams.get(name);
			String valueStr = "";
			for (int i = 0; i < values.length; i++) {
				valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
			}
			// 乱码解决，这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
			// valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
			params.put(name, valueStr);
		}

		// 获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
		// 商户订单号

		String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");

		// 支付宝交易号

		String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");

		// 交易状态
		String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"), "UTF-8");
		String total_fee = new String(request.getParameter("total_fee").getBytes("ISO-8859-1"), "UTF-8");
		BigDecimal price = new BigDecimal(total_fee);

		// 获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
		System.err.println("out_trade_no = " + out_trade_no + ",trade_no= " + trade_no + ",trade_status= "
				+ trade_status + ",total_fee = " + total_fee + ",price= " + price + "");
		if (AlipayNotify.verify(params)) {// 验证成功
			// ////////////////////////////////////////////////////////////////////////////////////////
			// 请在这里加上商户的业务逻辑程序代码

			// ——请根据您的业务逻辑来编写程序（以下代码仅作参考）——
			System.err.println("verify success");
			if (trade_status.equals("TRADE_FINISHED")) {
				// 判断该笔订单是否在商户网站中已经做过处理
				// 如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
				// 请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的
				// 如果有做过处理，不执行商户的业务程序

				// 注意：
				// 退款日期超过可退款期限后（如三个月可退款），支付宝系统发送该交易状态通知
			} else if (trade_status.equals("TRADE_SUCCESS")) {
				// 判断该笔订单是否在商户网站中已经做过处理
				// 如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
				// 请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的
				// 如果有做过处理，不执行商户的业务程序

				// 注意：
				// 付款完成后，支付宝系统发送该交易状态通知
				System.err.println("TRADE_FINISHED");
				GoodsOrderInfo order = orderInfoService.findByOrderNo(out_trade_no);
				if (order == null) {
					Error error = new Error();
					error.setAddTime(new Date());
					error.setError("支付宝支付出现问题,支付宝订单:" + out_trade_no + ",无法匹配不到系统的订单信息");
					error.setOrderNo(out_trade_no);
					errorService.add(error);
				} else {
					if (order.getPayState() == 2) {
						response.getWriter().println("success"); // 请不要修改或删除
						return;
					}
					Connection connection = C3p0DataSourceUtils.getConnection();
					Account account = accountService.findById(order.getAccountId());
					try {
						connection.setAutoCommit(false);
						QueryRunner runner = new QueryRunner();
						// 更新订单状态
						String sql = "update " + GoodsOrderInfo.class.getSimpleName().toLowerCase() + " set payState = "
								+ StateConstant.ORDER_PAY_STATE_PAY + ",state = " + StateConstant.ORDER_STATE_PAY
								+ ",payType='支付宝支付' ,isTimeOut = 0 where orderNo = '" + order.getOrderNo() + "'";
						runner.update(connection, sql);
						Goods product;
						List<GoodsOrderDetail> details = orderDetailService.findByOrderId(order.getId());
						if (details != null && details.size() > 0)
							for (GoodsOrderDetail detail : details) {
								product = productService.findById(detail.getProductId());
								product.setDateCount(product.getDateCount() + detail.getProductCount());
								product.setSellcount(product.getSellcount() + detail.getProductCount());
								sql = SqlBuilderUtils.builderUpdateSql(Goods.class, product);
								runner.update(connection, sql);
							}

						// 增加订单支付记录
						OrderPay orderPay = new OrderPay();
						orderPay.setAddTime(new Date());
						orderPay.setOrderId(order.getId());
						orderPay.setOrderNo(order.getOrderNo());
						orderPay.setTradeNo(trade_no);
						orderPay.setPayMethod("支付宝支付");
						orderPay.setPayPrice(price);
						orderPay.setPayState("TRADE_SUCCESS");
						orderPay.setRemark("支付成功");
						sql = SqlBuilderUtils.builderInsertSql(OrderPay.class, orderPay);
						runner.update(connection, sql);
						if (price.compareTo(order.getPayPrice()) == 0) {
							// 支付宝支付

						} else {
							// 用户用余额支付一部分
							// 更新账户余额 totalPrice - freePrice -
							// account.getMoney() 50 - 28
							BigDecimal p = order.getPayPrice().subtract(price);
							if (account == null) {
								try {
									connection.rollback();
								} catch (SQLException e1) {
									e1.printStackTrace();
								}
								Error error = new Error();
								error.setAddTime(new Date());
								error.setError("支付宝支付出现问题,支付宝订单:" + out_trade_no + ",无法匹配不到系统的用户信息");
								error.setOrderNo(order.getOrderNo());
								errorService.add(error);
							} else {
								// 添加账户记录
								if (account.getMoney().compareTo(p) < 0) {
									Error error = new Error();
									error.setAddTime(new Date());
									error.setError("支付宝支付出现问题,支付宝订单:" + out_trade_no + ",用户的余额有误,账户余额:"
											+ account.getMoney() + ",支付宝支付金额:" + price);
									error.setOrderNo(order.getOrderNo());
									errorService.add(error);
								} 

									AccountLog log = new AccountLog();
									log.setAccountId(account.getId());
									log.setAccountMobile(account.getMobile());
									log.setAddTime(new Date());
									log.setAfterMoney(account.getMoney().subtract(p));
									log.setBeforeMoney(account.getMoney());
									log.setMoney(p);
									log.setType(TypeConstant.log_type_yu_er_pay);
									account.setMoney(account.getMoney().subtract(p));
									sql = SqlBuilderUtils.builderInsertSql(AccountLog.class, log);
									runner.update(connection, sql);
									sql = "update account set money = "+account.getMoney() +" where id = " + account.getId();
									runner.update(connection, sql);
									// 增加订单支付记录
									OrderPay orderPay1 = new OrderPay();
									orderPay1.setAddTime(new Date());
									orderPay1.setOrderId(order.getId());
									orderPay1.setOrderNo(order.getOrderNo());
									orderPay1.setTradeNo(trade_no);
									orderPay1.setPayMethod("账户余额支付");
									orderPay1.setPayPrice(p);
									orderPay1.setPayState("支付成功");
									orderPay1.setRemark("账户余额支付,余额不足,部分用支付宝支付");
									sql = SqlBuilderUtils.builderInsertSql(OrderPay.class, orderPay1);
									runner.update(connection, sql);
								
							}
						}
						connection.commit();
						JPushUtils.sendGoodsOrderSuccess(order, account);
					} catch (Exception e) {
						try {
							connection.rollback();
						} catch (SQLException e1) {
							e1.printStackTrace();
						}
						e.printStackTrace();
						return;
					} finally {
						try {
							connection.close();
						} catch (SQLException e) {
							e.printStackTrace();
						}
					}
				}
			}

			// ——请根据您的业务逻辑来编写程序（以上代码仅作参考）——

			// 请不要修改或删除
			response.getWriter().println("success");
			// ////////////////////////////////////////////////////////////////////////////////////////
		} else {// 验证失败
			System.err.println("verify fail");
			response.getWriter().println("fail");
		}
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}

}
